local args = ngx.req.get_uri_args()
local user_id = args.uid
local item_id = args.item_id
local vote_id = args.vote_id
local vote_token = args.vote_token

-- 验证参数
if nil == user_id or "" == user_id then
    ngx.say('{"code":10000,"message":"请下载app进行投票"}')
    return
end

if nil == vote_id or "" == vote_id  then
    ngx.say('{"code":10000, "message":"vote_id不能为空"}')
    return
end

if nil == item_id or "" == item_id then
    ngx.say('{"code":10000,"message":"投票id不能为空"}')
    return
end
if nil == vote_token or "" == vote_token then
    ngx.say('{"code":10000,"message":"vote_token不能为空"}')
    return
end


local redis_client = require "lib.redis"
local redis = redis_client:new()

local user, err = redis:hget('app:uid:'..vote_id, user_id)

-- 验证是否登录
if nil == user then
    ngx.say('{"code":10000,"message":"请登录后进行投票"}')
    return
end

-- 判断验签是否正确
if vote_token ~= user then
    ngx.say('{"code":10001,"message":"验签不匹配"}')
    return
end

local ways = args.ways
-- 删除验签
if ways ~= "wechat" then
    redis:hset('app:uid:'..vote_id, user_id, '')
end

--开始投票
local vote = redis:hmget('rule:'..vote_id, 'allow_votes', 'brush_mode', 'start', 'end', 'is_pause')


if nil == vote then
    ngx.say('{"code":10000, "message":"活动不存在"}')
    return
end

--[[
    $pipe->hmset(
        'rule:'.$id,
        'allow_votes', $allow,
        'brush_mode', $mode,
        'start', $start,
        'end', $end,
        'is_pause', $activity->isPause
    );
]]

local time = ngx.time()
local start_at = vote[3] or 0
local end_at = vote[4] or (time + 1)
local is_paused = tonumber(vote[5])

--验证活动是否暂停
if is_paused == 1 then
    ngx.say('{"code":10000, "message":"活动已暂停"}')
    return
end

--验证投票时间
if time > tonumber(end_at) then
    ngx.say('{"code":10000, "message":"活动已经结束"}')
    return
end

if time < tonumber(start_at) then
    ngx.say('{"code":10000, "message":"活动还未开始"}')
    return
end


-- 验证投票次数，防刷票
local times_key = table.concat({"times", vote_id, user_id}, ":")
local allow_votes = tonumber(vote[1])
local mode = tonumber(vote[2])

if mode == 1 then
    local times_of_everday = redis:hget(times_key, ngx.today())
    local t = tonumber(times_of_everday) or 0
    if t >= allow_votes then
        ngx.say('{"code":10000, "message":"您今天的投票次数已用完"}')
        return
    end
elseif mode == 2 then
    local times_of_life = redis:hget(times_key, 'total')
    local t = tonumber(times_of_life) or 0
    if t >= allow_votes then
        ngx.say('{"code":10000, "message":"您的投票次数已用完"}')
        return
    end
else
    -- ngx.WARN
    ngx.log(ngx.ERR, "error vote brush_mode:", mode)
    ngx.say('{"code":10000, "message":"无效的投票项目"}')
    return    
end
ngx.record_user()
-- 投票计数，并记录相关数据
local ip = args.ip or "unknow"
local device_id = args.device_id or ""
local location = args.location or ""
local tenant_id = args.TenantID or ""
local uniqueid = string.lower(tenant_id..user_id)

local today = ngx.today()
local now = ngx.now()
local log = string.format(
    '{"ip":"%s","user":"%s","item":"%s","vote_at":"%s","device_id":"%s","location":"%s"}',
    ip,
    uniqueid,
    item_id,
    now,
    device_id,
    location
)

local ok, err = redis:eval([[
    local rank_key = "ranking:"..KEYS[4]
    local log_key = "logs:"..KEYS[4]..":"..KEYS[2]

    redis.call('HINCRBY', KEYS[1], 'total', 1)
    redis.call('HINCRBY', KEYS[1], KEYS[2], 1)
    redis.call('ZINCRBY', rank_key, 1, KEYS[3])
    redis.call('LPUSH', log_key, KEYS[5])
    return redis.status_reply("OK")
]], 5, times_key, today, item_id, vote_id, log)

if not ok then
    ngx.log(ngx.ERR, "redis execute scripts failed:", err)
    ngx.say('{"code":10000, "message":"投票失败"}')
    return
end

ngx.say('{"code":200, "message":"投票成功"}')
 

--[[
    累计这次投票
    KEYS[1]  -- 用户投票次数的key
    KEYS[2]  -- 今天的字符串表达式
    KEYS[3]  -- 投票项id
    KEYS[4]  -- vote_id
    KEYS[5]  -- 投票记录的json字符串
]]